package com.yfp.device.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.kangaroohy.dingtalk.entity.args.MarkdownArgs;
import com.kangaroohy.dingtalk.service.IDingTalkSender;
import com.yfp.common.core.exception.ServiceException;
import com.yfp.common.core.utils.DateUtils;
import com.yfp.common.core.utils.StringUtils;
import com.yfp.common.core.utils.WeixinRobotSender;
import com.yfp.common.log.service.AsyncLogService;
import com.yfp.common.security.utils.SecurityUtils;
import com.yfp.device.config.BajiushiProperties;
import com.yfp.device.domain.*;
import com.yfp.device.domain.dto.*;
import com.yfp.device.domain.vo.*;
import com.yfp.device.enums.CheckTypeEnum;
import com.yfp.device.enums.OrderStatus;
import com.yfp.device.enums.PackageStatus;
import com.yfp.device.mapper.*;
import com.yfp.device.mqtt.MqttGateway;
import com.yfp.device.service.DeviceCurrentComboStockService;
import com.yfp.device.service.MachineService;
import com.yfp.device.service.OrderComboService;
import com.yfp.device.service.OrderDetailService;
import com.yfp.device.utils.OssFile;
import com.yfp.device.utils.OssServiceImpl;
import com.yfp.goods.api.RemoteGoodsService;
import com.yfp.goods.domain.ComboDetailImg;
import com.yfp.goods.domain.GoodsNutritive;
import com.yfp.minapp.auth.api.RemoteClientService;
import com.yfp.system.api.RemoteLogService;
import com.yfp.system.api.domain.SysOperationLog;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 机器服务
 */
@Slf4j
@Service
public class MachineServiceImpl implements MachineService {
    @Resource
    private MachineTempWarnMapper machineTempWarnMapper;
    @Resource
    private OrderComboService orderComboService;
    @Resource
    private OrderDetailService orderDetailService;
    @Resource
    private DeviceCurrentComboStockService deviceCurrentComboStockService;
    @Resource
    private ComboMapper comboMapper;
    @Resource
    private ComboGoodsMapper comboGoodsMapper;
    @Resource
    private ImgResourceMapper imgResourceMapper;
    @Resource
    private TagComboMapper tagComboMapper;
    @Resource
    private GoodsMapper goodsMapper;
    @Resource
    private DeviceCurrentComboPlanMapper deviceCurrentComboPlanMapper;
    @Resource
    private DeviceComboPlanNumMapper deviceComboPlanNumMapper;
    @Resource
    private OrderListMapper orderListMapper;
    @Resource
    private RedissonClient redissonClient;
    @Resource
    private ClientMapper clientMapper;
    @Resource
    private MqttGateway mqttGateway;
    @Resource
    private RemoteClientService remoteClientService;
    @Resource
    private RemoteLogService remoteLogService;
    @Resource
    private AsyncLogService asyncLogService;

    @Autowired
    private ApplicationContext applicationContext;

    private final MachineMapper machineMapper;

    private final MachineLogMapper machineLogMapper;

    private final MachineRoadMapper machineRoadMapper;

    private final DeviceCurrentComboPlanRoadMapper deviceCurrentComboPlanRoadMapper;

    private final DeviceCurrentComboPlanStockMapper deviceCurrentComboPlanStockMapper;

    private final MachineDamageMapper machineDamageMapper;

    private final MachineDamageDetailMapper machineDamageDetailMapper;

    private final MachineEventTrackMapper machineEventTrackMapper;

    private final OssServiceImpl ossService;

    private final SqlSessionFactory sqlSessionFactory;

    private final MachineErrorMapper machineErrorMapper;

    private final MachineAdMapper machineAdMapper;

    private final PositionTypeMapper positionTypeMapper;

    private final MachineDebugLogMapper machineDebugLogMapper;

    @Resource
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private RemoteGoodsService remoteGoodsService;

    @Autowired
    private IDingTalkSender talkSender;

    @Autowired
    private BajiushiProperties bajiushiProperties;
    // @Resource
    // private SysDictDataService sysDictDataService;


    public MachineServiceImpl(MachineMapper machineMapper, MachineLogMapper machineLogMapper, MachineRoadMapper machineRoadMapper, MachineDamageMapper machineDamageMapper, MachineDamageDetailMapper machineDamageDetailMapper, MachineEventTrackMapper machineEventTrackMapper, MachineNetWarnMapper machineNetWarnMapper, MachineTempWarnMapper machineTempWarnMapper, MachineInventoryWarnMapper machineInventoryWarnMapper, MachineExpireWarnMapper machineExpireWarnMapper, DeviceCurrentComboPlanStockMapper deviceCurrentComboPlanStockMapper, SqlSessionFactory sqlSessionFactory, OssServiceImpl ossService, MachineErrorMapper machineErrorMapper, MachineAdMapper machineAdMapper, PositionTypeMapper positionTypeMapper, DeviceCurrentComboPlanRoadMapper deviceCurrentComboPlanRoadMapper, MachineDebugLogMapper machineDebugLogMapper) {
        this.machineMapper = machineMapper;
        this.machineLogMapper = machineLogMapper;
        this.machineRoadMapper = machineRoadMapper;
        this.machineDamageMapper = machineDamageMapper;
        this.machineDamageDetailMapper = machineDamageDetailMapper;
        this.machineEventTrackMapper = machineEventTrackMapper;
        this.deviceCurrentComboPlanStockMapper = deviceCurrentComboPlanStockMapper;
        this.sqlSessionFactory = sqlSessionFactory;
        this.ossService = ossService;
        this.machineErrorMapper = machineErrorMapper;
        this.machineAdMapper = machineAdMapper;
        this.positionTypeMapper = positionTypeMapper;
        this.deviceCurrentComboPlanRoadMapper = deviceCurrentComboPlanRoadMapper;
        this.machineDebugLogMapper = machineDebugLogMapper;
    }

    /**
     * 更新机器经纬度
     *
     * @param machineSn 机器编号
     * @param longitude 经度
     * @param latitude  纬度
     * @return 响应体
     */
    @Override
    public R<?> updateLatAndLon(String machineSn, String longitude, String latitude) {
        try {
            Machine machine = new Machine();
            machine.setMachineId(machineSn);
            machine.setLatitude(latitude);
            machine.setLongitude(longitude);
            machineMapper.updateByPrimaryKeySelective(machine);
            log.info("更新经纬度成功");
            return R.ok();
        } catch (Exception e) {
            log.error("更新经纬度失败", e);
            return R.fail();
        }
    }

    /**
     * 更新机器温度
     *
     * @param machineSn   机器编号
     * @param temperature 温度
     * @return 响应体
     */
    @Override
    public R<?> updateTemperature(String machineSn, String temperature) {
        try {
            boolean number = NumberUtil.isNumber(temperature);
            if (!number){
                return R.fail("温度格式不正确");
            }
            Machine machine = new Machine();
            machine.setMachineId(machineSn);
            machine.setTemperature(temperature);
            machineMapper.updateByPrimaryKeySelective(machine);
            MachineTemp machineTemp = new MachineTemp();
            machineTemp.setMachineId(machineSn);
            machineTemp.setTemp(Integer.parseInt(temperature));
            machineMapper.insertMachineTemp(machineTemp);
            log.info("更新机器温度成功");
            return R.ok();
        } catch (Exception e) {
            log.error("更新机器温度失败", e);
            return R.fail();
        }
    }

    /**
     * 上报设备部件状态
     *
     * @param machineSn     机器编号
     * @param checkTypeEnum 部件类型
     * @param isWork        状态
     * @return 响应体
     */
    @Override
    public R<?> reportComponent(String machineSn, CheckTypeEnum checkTypeEnum, Integer isWork) {
        try {
            Machine machine = new Machine();
            machine.setMachineId(machineSn);
            log.info("修改设备部件状态，设备id:{},部件类型:{},状态:{}",machineSn,checkTypeEnum,isWork);
            switch (checkTypeEnum) {
                case OpenDoor -> machine.setOpenDoorCheck(isWork);
                case CloseDoor -> machine.setCloseDoorCheck(isWork);
                case OutMeal -> machine.setOutMealCheck(isWork);
                case TakeMeal -> machine.setTakeMealCheck(isWork);
                case Temperature -> machine.setTemperatureCheck(isWork);
                case Network -> machine.setNetworkCheck(isWork);
                case Device -> machine.setDeviceCheck(isWork);
            }
            machineMapper.updateByPrimaryKeySelective(machine);
            log.info("上报设备部件状态成功");
            return R.ok();
        } catch (Exception e) {
            log.error("上报设备部件状态失败", e);
            return R.fail();
        }
    }

    /**
     * 上传设备日志文件
     *
     * @param machineSn 机器编号
     * @param logFile   日志文件
     * @return 响应体
     */
    public R<?> uploadLogFile(String machineSn, MultipartFile logFile) {
        try {
            OssFile ossFile = ossService.uploadFile(logFile);
            MachineLog record = new MachineLog();
            record.setLogFileName(ossFile.getFileName());
            record.setUrl(ossFile.getUrl());
            record.setMachineId(machineSn);
            record.setCreateTime(new Date());
            machineLogMapper.insert(record);
            log.info("上传设备日志文件");
            return R.ok();
        } catch (Exception e) {
            log.error("上传设备日志文件");
            return R.fail();
        }
    }

    /**
     * 机器报损
     *
     * @param machineSn    机器编号
     * @param userName     用户名
     * @param machineRoads 货道
     * @return 响应体
     */
    @Override
    public R<?> damageReport(String machineSn, String userName, List<MachineRoadVo> machineRoads) {
        log.info("设备id:{},报损参数:{}",machineSn,machineRoads);
        SysOperationLog sysOperationLog = new SysOperationLog();
        sysOperationLog.setMachineId(machineSn);
        sysOperationLog.setAccount(userName);
        sysOperationLog.setType(2);
        sysOperationLog.setParameter(machineRoads.toString());
        asyncLogService.addOperationLog(sysOperationLog);
        try {
//            // step1 下架/清空货道
//            deviceCurrentComboPlanRoadMapper.deleteByMachineId(machineSn);
//            log.info("清空货道{}成功", machineSn);
//            deviceCurrentComboPlanStockMapper.deleteByMachineId(machineSn);
//            log.info("清空库存{}成功", machineSn);


            // 查询该设备 今日 付过钱没退款的，但是没工单的套餐id
            List<String> comboIds = orderListMapper.getByMachineIdAndStatus(machineSn);
            if (!comboIds.isEmpty()) {
                // key是套餐id  value为该套餐出现次数
                Map<String, Long> countMap = comboIds.stream()
                        .collect(Collectors.groupingBy(n -> n, Collectors.counting()));
                for (String comboId : countMap.keySet()) {
                    // 套餐数量
                    Long num = countMap.get(comboId);
                    // 获取为该套餐的货道信息，根据货道号从小到大排序
                    List<MachineRoadVo> dtoList = machineRoads.stream().filter(item -> item.getComboId().equals(comboId))
                            .sorted((s1,s2) -> Integer.compare(Integer.parseInt(s1.getRoadNo()), Integer.parseInt(s2.getRoadNo()))).toList();

                    // 遍历货道信息，直到将该套餐数量减完
                    for (MachineRoadVo damageDTO : dtoList) {
                        if (num <= 0) {
                            break;
                        }
                        // 获取该货道的数量
                        Integer comboNum = damageDTO.getInventory();

                        // 判断如果待减数量大于货道数量    则直接减掉
                        if (num >= comboNum) {
                            num -= comboNum;
                            // 赋值为0
                            damageDTO.setInventory(0);
                        } else {
                            Long l = comboNum - num;
                            damageDTO.setInventory(l.intValue());
                            num = 0L;
                        }
                    }

                    // 将修改后的套餐数量赋值到对应的货道
                    Map<String, Integer> numMap = dtoList.stream().collect(Collectors.toMap(MachineRoadVo::getRoadNo, MachineRoadVo::getInventory));
                    for (MachineRoadVo damageDTO : machineRoads) {
                        if (numMap.containsKey(damageDTO.getRoadNo())) {
                            Integer comboNum = numMap.get(damageDTO.getRoadNo());
                            damageDTO.setInventory(comboNum);
                        }
                    }
                }
            }



            // 修改数量为0
            deviceCurrentComboPlanRoadMapper.updateComboNum(machineSn);
            deviceCurrentComboPlanStockMapper.updateComboNum(machineSn);

            // step2 记录报损信息
            DateTime date = DateUtil.date();
            MachineDamage machineDamage = new MachineDamage();
            machineDamage.setMachineId(machineSn);
            machineDamage.setUserName(userName);
            machineDamage.setCreatTime(date);
            machineDamage.setUpdateTime(date);
            machineDamageMapper.insert(machineDamage);
            log.info("保存报损记录");
            log.info("设备id:{},最终报损数据:{}",machineSn,machineRoads);
            machineRoads.forEach(m -> {
                MachineDamageDetail damageDetail = new MachineDamageDetail();
                damageDetail.setMachineId(machineSn);
                damageDetail.setComboId(m.getComboId());
                damageDetail.setRoadNo(m.getRoadNo());
                damageDetail.setReportNum(m.getInventory());
                damageDetail.setCreateTime(date);
                damageDetail.setUpdateTime(date);
                machineDamageDetailMapper.insert(damageDetail);
            });
            log.info("保存报损详情成功");
            return R.ok();
        } catch (Exception e) {
            log.error("机器报损失败", e);
            return R.fail("机器报损失败");
        }
    }

    /**
     * 同步货道库存
     *
     * @param machineSn      机器编号
     * @param userName       用户名
     * @param machineRoadVos 货道
     * @return 响应体
     */
    @Override
    public R<?> syncRoadInventory(String machineSn, String userName, List<MachineRoadVo> machineRoadVos) {
        try {
            List<MachineRoad> machineRoads = new ArrayList<>();
            machineRoadVos.forEach(m -> {
                MachineRoad road = new MachineRoad();
                road.setMachineId(machineSn);
                road.setInventory(m.getInventory());
                road.setRoadNo(m.getRoadNo());
                machineRoads.add(road);
            });
            // step 更新货道
            machineRoadMapper.updateMachineRoads(machineRoads);
            return R.ok();
        } catch (Exception e) {
            log.error("机器报损失败", e);
            return R.fail("机器报损失败");
        }
    }

    /**
     * 上传埋点日志文件
     *
     * @param machineSn      机器
     * @param type           类型
     * @param eventTrackFile 埋点文件
     * @return 响应体
     */
    @Override
    public R<?> uploadEventTrackFile(String machineSn, Integer type, MultipartFile eventTrackFile) {
        try {
            OssFile ossFile = ossService.uploadFile(eventTrackFile);
            MachineEventTrack record = new MachineEventTrack();
            record.setFileName(ossFile.getFileName());
            record.setType(type);
            record.setUrl(ossFile.getUrl());
            record.setMachineId(machineSn);
            record.setCreateTime(new Date());
            machineEventTrackMapper.insertSelective(record);
            log.info("上传埋点日志文件成功");
            return R.ok();
        } catch (Exception e) {
            log.error("上传埋点日志文件失败");
            return R.fail("上传埋点日志文件失败");
        }
    }

    /**
     * 钉钉机器人发送信息
     *
     * @param title
     * @param text
     */
    public void sendDingTalk(String title, String text) {
        talkSender.send(MarkdownArgs.builder().title(title).text(text).build());
    }


    /**
     * 同步告警
     *
     * @param request 请求体
     * @return 响应体
     */
    @Override
    public R<?> syncWarn(SyncWarnRequest request) {
        SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false);
//        Machine machine = machineMapper.selectByMachineSn(request.getMachineSn());
//        String warnTime = System.currentTimeMillis() + "";
        try {
            if (request.getExpireWarnVoList() != null && !request.getExpireWarnVoList().isEmpty()) {
                MachineExpireWarnMapper mapper = sqlSession.getMapper(MachineExpireWarnMapper.class);
                request.getExpireWarnVoList().forEach(m -> {
                    MachineExpireWarn machineExpireWarn = new MachineExpireWarn();
                    machineExpireWarn.setWarnId(m.getWarnId());
                    machineExpireWarn.setMachineId(request.getMachineSn());
                    machineExpireWarn.setComboId(m.getComboId());
                    machineExpireWarn.setComboName(m.getComboName());
                    machineExpireWarn.setClearFlag(0);
                    machineExpireWarn.setNumber(m.getNumber());
                    machineExpireWarn.setCreatTime(new Date());
                    machineExpireWarn.setWarnTime(m.getWarnTime());
                    mapper.insertSelective(machineExpireWarn);
                    // markdown类型
                });

//                warnTime = request.getExpireWarnVoList().get(0).getWarnTime() == null ? warnTime : request.getExpireWarnVoList().get(0).getWarnTime();
//                Thread.sleep(1000);
//                String text = "### 餐品过期报警" +
//                        "\n - 设备编号： " + machine.getMachineSn() +
//                        "\n - 设备名称： " + machine.getMachineName() +
//                        "\n - 报警时间： " + DateUtils.parseLongToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, Long.parseLong(warnTime));
//                sendDingTalk("餐品过期报警", text);
                sqlSession.commit();
                sqlSession.clearCache();
            }
            if (request.getTempWarnVoList() != null && !request.getTempWarnVoList().isEmpty()) {
                MachineTempWarnMapper mapper = sqlSession.getMapper(MachineTempWarnMapper.class);
                request.getTempWarnVoList().forEach(m -> {
                    MachineTempWarn machineTempWarn = new MachineTempWarn();
                    machineTempWarn.setWarnId(m.getWarnId());
                    machineTempWarn.setMachineId(request.getMachineSn());
                    machineTempWarn.setClearFlag(0);
                    machineTempWarn.setWarnTime(m.getWarnTime());
                    machineTempWarn.setExceptionTemp(m.getExceptionTemp());
                    machineTempWarn.setRecoverTime(m.getRecoverTime());
                    machineTempWarn.setCreatTime(new Date());
                    mapper.insertSelective(machineTempWarn);
                });
//                warnTime = request.getTempWarnVoList().get(0).getWarnTime() == null ? warnTime : request.getTempWarnVoList().get(0).getWarnTime();
//                Thread.sleep(1000);
//                String text = "### 异常温度报警" +
//                        "\n - 设备编号： " + machine.getMachineSn() +
//                        "\n - 设备名称： " + machine.getMachineName() +
//                        "\n - 当前温度： " + request.getTempWarnVoList().get(0).getExceptionTemp() + "°" +
//                        "\n - 报警时间： " + DateUtils.parseLongToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, Long.parseLong(warnTime));
//                sendDingTalk("异常温度报警", text);

                sqlSession.commit();
                sqlSession.clearCache();
            }
            if (request.getNetWarnVoList() != null && !request.getNetWarnVoList().isEmpty()) {
                MachineNetWarnMapper mapper = sqlSession.getMapper(MachineNetWarnMapper.class);
                request.getNetWarnVoList().forEach(m -> {
                    MachineNetWarn machineNetWarn = new MachineNetWarn();
                    machineNetWarn.setWarnId(m.getWarnId());
                    machineNetWarn.setMachineId(request.getMachineSn());
                    machineNetWarn.setClearFlag(0);
                    machineNetWarn.setCreatTime(new Date());
                    machineNetWarn.setRecoverTime(m.getRecoverTime());
                    machineNetWarn.setOfflineDuration(m.getOfflineDuration());
                    machineNetWarn.setOfflineTime(m.getOfflineTime());
                    machineNetWarn.setOnlineDuration(m.getOnlineDuration());
                    mapper.insertSelective(machineNetWarn);
                });
//                warnTime = request.getNetWarnVoList().get(0).getOfflineTime() == null ? warnTime : request.getNetWarnVoList().get(0).getOfflineTime();
//                Thread.sleep(1000);
//                String text = "### 网络异常报警" +
//                        "\n - 设备编号： " + machine.getMachineSn() +
//                        "\n - 设备名称： " + machine.getMachineName() +
//                        "\n - 报警时间： " + DateUtils.parseLongToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, Long.parseLong(warnTime));
//                sendDingTalk("网络异常报警", text);
                sqlSession.commit();
                sqlSession.clearCache();
            }
            if (request.getInventoryWarnVoList() != null && !request.getInventoryWarnVoList().isEmpty()) {
                MachineInventoryWarnMapper mapper = sqlSession.getMapper(MachineInventoryWarnMapper.class);
                StringBuffer inventory = new StringBuffer();
                request.getInventoryWarnVoList().forEach(m -> {
                    MachineInventoryWarn machineInventoryWarn = new MachineInventoryWarn();
                    machineInventoryWarn.setWarnId(m.getWarnId());
                    machineInventoryWarn.setMachineId(request.getMachineSn());
                    machineInventoryWarn.setInventory(m.getInventory());
                    machineInventoryWarn.setWarnTime(null == m.getWarnTime() ? System.currentTimeMillis() + "" : m.getWarnTime());
                    machineInventoryWarn.setClearFlag(0);
                    machineInventoryWarn.setComboId(m.getComboId());
                    machineInventoryWarn.setComboName(m.getComboName());
                    machineInventoryWarn.setCreatTime(new Date());
                    inventory.append("套餐名称： " + m.getComboName() + "套餐剩余份数：" + m.getInventory());
                    mapper.insertSelective(machineInventoryWarn);
                });
//                warnTime = request.getInventoryWarnVoList().get(0).getWarnTime() == null ? warnTime : request.getInventoryWarnVoList().get(0).getWarnTime();
//                Thread.sleep(1000);
//                String text = "### 库存报警" +
//                        "\n - 设备编号： " + machine.getMachineSn() +
//                        "\n - 设备名称： " + machine.getMachineName() +
//                        "\n - 报警内容： " + inventory.toString() +
//                        "\n - 报警时间： " + DateUtils.parseLongToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, Long.parseLong(warnTime));
//                sendDingTalk("网络异常报警", text);
                sqlSession.commit();
                sqlSession.clearCache();
            }
            log.info("同步告警成功");
            return R.ok();
        } catch (Exception e) {
            log.error("同步告警失败", e);
            sqlSession.rollback();
            sqlSession.close();
            return R.fail("同步告警失败");
        } finally {
            log.debug("关闭sqlSession");
            sqlSession.close();
        }
    }

    /**
     * 故障上报
     *
     * @param request 请求体
     * @return 响应体
     */
    @Override
    public R<?> reportError(ReportErrorRequest request) {
        try {
            MachineError machineError = new MachineError();
            machineError.setMachineId(request.getMachineSn());
            machineError.setMachineType(request.getMachineType());
            machineError.setErrorCode(request.getErrCode());
            machineError.setErrorDesc(request.getErrDesc());
            machineError.setErrorName(request.getErrName());
            machineError.setErrorType(request.getErrType());
            machineError.setErrorTime(request.getErrTime());
            machineError.setErrorRepairTime(request.getRepairTime());
            machineError.setContainerNo(request.getContainerNo());
            machineErrorMapper.insertSelective(machineError);
            return R.ok("故障上报成功");
        } catch (Exception e) {
            log.error("故障上报失败", e);
            return R.fail("故障上报失败");
        }
    }

    /**
     * 修复故障
     *
     * @param machineSn  机器编号
     * @param errCode    故障代码
     * @param repairTime 修复时间
     * @return 响应体
     */
    @Override
    public R<?> repairError(String machineSn, String errCode, String repairTime) {
        try {
            machineErrorMapper.updateByMachineSnAndErrCode(machineSn, errCode, repairTime);
            log.info("修复故障成功");
            return R.ok("修复故障成功");
        } catch (Exception e) {
            log.error("修复故障失败", e);
            return R.fail("修复故障失败");
        }
    }

    /**
     * 上报VMC连接状态
     *
     * @param machineSn 机器编号
     * @param vmcStatus VMC连接状态
     * @return 响应体
     */
    @Override
    public R<?> reportVMCStatus(String machineSn, String vmcStatus) {
        try {
            Machine machine = new Machine();
            machine.setMachineId(machineSn);
            machine.setVmcStatus(vmcStatus);
            machineMapper.updateByPrimaryKeySelective(machine);
            log.info("{}上报VMC连接状态成功", machineSn);
            return R.ok("上报VMC连接状态成功");
        } catch (Exception e) {
            log.error("上报VMC连接状态失败", e);
            return R.fail("上报VMC连接状态失败");
        }
    }

    /**
     * 设备在线
     *
     * @param machineSn 设备编号
     * @return 响应体
     */
    @Override
    public R<?> online(String machineSn) {
        try {
            Machine machine = new Machine();
            machine.setMachineId(machineSn);
            machine.setOnlineStatus(1);
            machineMapper.updateByPrimaryKeySelective(machine);
            log.info("{}设备在线设置成功", machineSn);
            return R.ok("设备在线设置成功");
        } catch (Exception e) {
            log.error("设备在线设置失败", e);
            return R.fail("设备在线设置失败");
        }
    }

    /**
     * 更新广告状态
     *
     * @param machineSn  机器编号
     * @param adId       广告id
     * @param playStatus 播放状态（1：待播放 2：播放中 3：已结束）
     * @return 响应体
     */
    @Override
    public R<?> updateAdStatus(String machineSn, String adId, Integer playStatus) {
        try {
            machineAdMapper.updatePlayStatus(machineSn, adId, playStatus);
            log.info("{}更新广告状态成功", machineSn);
            return R.ok("更新广告状态成功");
        } catch (Exception e) {
            log.error("更新广告状态失败", e);
            return R.fail("更新广告状态失败");
        }
    }

    /**
     * 查询设备序号
     *
     * @param machineSn 机器编号
     * @return 设备序号
     */
    @Override
    public R<String> qryMachineSerial(String machineSn) {
        try {
            Machine machine = machineMapper.selectByPrimaryKey(machineSn);
            if (machine == null) {
                throw new Exception("设备不存在");
            }
            log.info("{}查询设备序号成功", machineSn);
            return R.ok(machine.getMachineSn(), "查询设备序号成功");
        } catch (Exception e) {
            log.error("查询设备序号失败", e);
            return R.fail("查询设备序号失败");
        }
    }

    /**
     * 查询设备id
     *
     * @param machineSerial 机器编号
     * @return 响应体
     */
    public R<String> qryMachineSn(String machineSerial) {
        try {
            Machine machine = machineMapper.selectByMachineSn(machineSerial);
            if (machine == null) {
                throw new Exception("设备不存在");
            }
            log.info("{}查询设备序号成功", machineSerial);
            return R.ok(machine.getMachineId(), "查询设备序号成功");
        } catch (Exception e) {
            log.error("查询设备序号失败", e);
            return R.fail("查询设备序号失败");
        }
    }

    /**
     * 查询设备运营时间
     *
     * @param machineSn 机器编号
     * @return 响应体
     */
    @Override
    public R<QryMachineOpTimeResponse> qryMachineOpTime(String machineSn) {
        try {
            // 获取点位信息
            PositionType positionType = positionTypeMapper.selectByMachineSn(machineSn);
            if (positionType == null) {
                log.error("设备售卖时间不存在，设置默认值");
                positionType = new PositionType();
                positionType.setSaleBeginTime("6:00");
                positionType.setSaleEndTime("23:00");
            }
            // 获取设备信息
            Machine machine = machineMapper.selectByMachineSn(machineSn);
            log.info("{}查询设备运营时间成功", machineSn);
            QryMachineOpTimeResponse response = new QryMachineOpTimeResponse();
            response.setMachineSn(machineSn);
            response.setStartTime(positionType.getSaleBeginTime());
            response.setEndTime(positionType.getSaleEndTime());
            response.setThreshold(machine.getThreshold());
            return R.ok(response, "查询设备序号成功");
        } catch (Exception e) {
            log.error("查询设备运营时间失败", e);
            return R.fail("查询设备运营时间失败");
        }
    }

    /**
     * 检查机器编号
     *
     * @param machineSn 机器编号
     * @return 响应体
     */
    @Override
    public R<?> checkMachineSn(String machineSn) {
        try {
            Machine machine = machineMapper.selectByPrimaryKey(machineSn);
            if (machine == null) {
                return R.fail("设备编号不存在");
            }
            if (machine.getOnlineStatus() == 1) {
                return R.fail("设备编号被占用");
            }
            return R.ok("机器编号可用");
        } catch (Exception e) {
            log.error("检查机器编号失败", e);
            return R.fail("检查机器编号失败");
        }
    }

    /**
     * 更新运营状态
     *
     * @param machineSn       机器编号
     * @param operationStatus 运营状态（1：运营中，2：休息中 3：故障中 4: 补货）
     * @return 响应体
     */
    public R<?> updateOperationStatus(String machineSn, Integer operationStatus) {
        try {
            Machine machine = machineMapper.selectByPrimaryKey(machineSn);
            if (machine == null) {
                return R.fail("设备编号不存在");
            }
            Machine machineNew = new Machine();
            machineNew.setMachineId(machineSn);
            machineNew.setOperationStatus(operationStatus);
            machineMapper.updateByPrimaryKeySelective(machineNew);
            log.info("更新运营状态成功, 设备编号：{}，状态：{}", machineSn, operationStatus);
            return R.ok("更新运营状态成功");
        } catch (Exception e) {
            log.error("更新运营状态失败", e);
            return R.fail("更新运营状态失败");
        }
    }

    /**
     * 获取机器信息
     *
     * @param machineSn 机器编号
     * @return 响应体
     */
    public R<?> qryMachineInfo(String machineSn) {
        try {
            Machine machine = machineMapper.selectByPrimaryKey(machineSn);
            if (machine == null) {
                return R.fail("设备编号不存在");
            }
            String operationMobile = machineMapper.findOperationMobile(machine.getPositionId());
            MachineInfoVo machineInfoVo = new MachineInfoVo();
            machineInfoVo.setMachineName(machine.getMachineName());
            machineInfoVo.setPositionAddr(machine.getPositionAddr());
            machineInfoVo.setServiceTel(operationMobile);
            machineInfoVo.setAssociationUrl(machineMapper.selectAsscoiationCodeByPositionId(machine.getPositionId()));
            machineInfoVo.setMiniAppUrl(bajiushiProperties.getDomain()+"/openapp?machineId="+machine.getMachineId());
            return R.ok(machineInfoVo, "获取机器信息成功");
        } catch (Exception e) {
            log.error("获取机器信息失败", e);
            return R.fail("获取机器信息失败");
        }
    }


    /**
     * 查询日志文件
     *
     * @param request 请求体
     * @return 响应体
     */
    public R<QryLogFilesResponse> qryLogFiles(QryLogFilesRequest request) {
        try {
            List<MachineLog> machineLogs = machineLogMapper
                    .selectByMachineSnAndTime(request.getMachineSn(),
                            DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", request.getBeginTime()),
                            DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", request.getEndTime()));
            QryLogFilesResponse qryLogFilesResponse = new QryLogFilesResponse();
            qryLogFilesResponse.setMachineSn(request.getMachineSn());
            qryLogFilesResponse.setMachineLogs(machineLogs);
            return R.ok(qryLogFilesResponse, "查询日志文件成功");
        } catch (Exception e) {
            log.error("查询日志文件失败", e);
            return R.fail("查询日志文件失败");
        }
    }

    /**
     * 上传调试日志
     *
     * @param machineDebugLogVo 请求体
     * @return 响应体
     */
    public R<?> uploadDebugLog(MachineDebugLogVo machineDebugLogVo) {
        try {
            MachineDebugLog machineDebugLog = new MachineDebugLog();
            machineDebugLog.setCreateTime(new Date());
            machineDebugLog.setMachineId(machineDebugLogVo.getMachineSn());
            machineDebugLog.setTitle(machineDebugLogVo.getTitle());
            machineDebugLog.setLogContent(machineDebugLogVo.getLogContent());
            machineDebugLogMapper.insertSelective(machineDebugLog);
            return R.ok("上传调试日志成功");
        } catch (Exception e) {
            log.error("上传调试日志失败", e);
            return R.fail("上传调试日志失败");
        }
    }

    /**
     * 查询调试日志
     *
     * @param request 请求体
     * @return 响应体
     */
    public R<QryDebugLogsResponse> qryDebugLogs(QryDebugLogsRequest request) {
        try {
            QryDebugLogsResponse qryDebugLogsResponse = new QryDebugLogsResponse();
            AtomicReference<List<MachineDebugLogVo>> machineDebugLogVos = new AtomicReference<>(new ArrayList<>());
            List<MachineDebugLog> machineDebugLogs = machineDebugLogMapper.selectByMachineSnAndTime(request.getMachineSn(),
                    DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", request.getBeginTime()),
                    DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", request.getEndTime()));
            machineDebugLogs.forEach(m -> {
                MachineDebugLogVo machineDebugLogVo = new MachineDebugLogVo();
                machineDebugLogVo.setMachineSn(m.getMachineId());
                machineDebugLogVo.setTitle(m.getTitle());
                machineDebugLogVo.setLogContent(m.getLogContent());
                machineDebugLogVo.setCreateTime(m.getCreateTime());
                machineDebugLogVos.get().add(machineDebugLogVo);
            });
            qryDebugLogsResponse.setMachineDebugLogVos(machineDebugLogVos.get());
            return R.ok(qryDebugLogsResponse, "查询调试日志成功");
        } catch (Exception e) {
            log.error("查询调试日志失败", e);
            return R.fail("查询调试日志失败");
        }
    }

    /**
     * 同步库存
     *
     * @param machineSn 机器编号
     * @return 响应体
     */
    public R<SyncMachineRoadResponse> syncMachineRoad(String machineSn) {
        try {
            SyncMachineRoadResponse syncMachineRoadResponse = new SyncMachineRoadResponse();
            List<DeviceCurrentComboPlanRoad> deviceCurrentComboPlanRoads = deviceCurrentComboPlanRoadMapper.selectByMachineSn(machineSn);
            List<MachineRoadVo> machineRoadVos = new ArrayList<>();
            deviceCurrentComboPlanRoads.forEach(m -> {
                MachineRoadVo machineRoadVo = new MachineRoadVo();
                machineRoadVo.setRoadNo(m.getRoadNumber());
                machineRoadVo.setComboId(m.getComboId());
                machineRoadVo.setInventory(Integer.parseInt(m.getComboNum().trim()));
                machineRoadVos.add(machineRoadVo);
            });
            syncMachineRoadResponse.setMachineSn(machineSn);
            syncMachineRoadResponse.setMachineRoads(machineRoadVos);
            return R.ok(syncMachineRoadResponse, "同步库存成功");
        } catch (Exception e) {
            log.error("同步库存失败", e);
            return R.fail("同步库存失败");
        }
    }

    /**
     * 获取设备库存报警阈值
     *
     * @param machineSn 机器编号
     * @return 响应体
     */
    public R<QryMachineThresholdResponse> qryMachineThreshold(String machineSn) {
        try {
            QryMachineThresholdResponse qryMachineThresholdResponse = new QryMachineThresholdResponse();
            // Machine machine = machineMapper.selectByMachineSn(machineSn);
            qryMachineThresholdResponse.setThreshold("5");
            qryMachineThresholdResponse.setMachineSn(machineSn);
            return R.ok(qryMachineThresholdResponse, "获取设备库存报警阈值成功");
        } catch (Exception e) {
            log.error("获取设备库存报警阈值失败", e);
            return R.fail("获取设备库存报警阈值失败");
        }
    }

    @Override
    public Machine getById(String machineId) {
        return machineMapper.getById(machineId);
    }

    /**
     * 上报暂存柜空余数量
     *
     * @param machineId
     * @param count
     * @return
     */
    @Override
    public R<String> reportTemporaryLockers(String machineId, String count) {
        String key = "temporaryLockers" + machineId;
        redisTemplate.opsForValue().set(key, count);
        log.info("小程序设备:{},上报暂存柜可用数量:{}", machineId, count);
        return R.ok();
    }

    /**
     * 设备上报收到立即制作信息
     *
     * @param packageStatus
     * @return
     */
    @Override
    @Transactional
    public R<String> reportPackageStatus(com.yfp.device.domain.PackageStatus packageStatus) {
        log.info("设备上报收到立即制作消息:{}", packageStatus);
        OrderCombo orderCombo = orderComboService.getById(packageStatus.getOrderId());
        if (orderCombo == null) {
            return R.fail("订单不存在");
        }
        // 判断订单状态
        if (!orderCombo.getStatus().equals(OrderStatus.AwaitPackage.getStatus())) {
            log.info("订单状态不支持制作");
            return R.fail("该订单状态不支持该操作");
        }
        // 设置状态
        List<OrderDetail> orderDetails = new ArrayList<>();
        OrderDetail orderDetail = null;
        for (com.yfp.device.domain.PackageStatus.Package aPackage : packageStatus.getPackageList()) {
            orderDetail = new OrderDetail();
            orderDetail.setOrderDetailId(aPackage.getOrderDetailId());
            orderDetail.setStatus(PackageStatus.WaitingToBeMade.getStatus());
            orderDetails.add(orderDetail);
        }
        // 批量修改状态
        orderDetailService.updateOrderDetail(orderDetails);
        return R.ok();
    }

    /**
     * 获取线上库存信息
     *
     * @return
     */
    @Override
    public R<List<DeviceCurrentComboStock>> getDeviceComboStockInfo() {
        // 获取设备信息
        String machineId = SecurityUtils.getUsername();
        if (StringUtils.isEmpty(machineId)) {
            log.info("设备未登录");
            return R.fail("设备未登录");
        }
        // 根据设备id获取线上库存信息
        List<DeviceCurrentComboStock> stockList = deviceCurrentComboStockService.getByMachineId(machineId);
        return R.ok(stockList);
    }


    /**
     * 获取明日预告
     *
     * @return
     */
    @Override
    public R<List<ForeshowVo>> deviceComboForecastList() {
        String machineId = SecurityUtils.getUsername();
        if (StringUtils.isEmpty(machineId)) {
            log.info("设备未登录");
            return R.fail("设备未登录");
        }
//        String machineId = "24051302000038";
        /// 获取当前时间
        LocalDateTime now = LocalDateTime.now();
        // 获取明天的日期并设置时间为早上八点
        LocalDateTime tomorrowEightAM = now.plusDays(1).with(LocalTime.of(8, 0));
        // 将 LocalDateTime 转换为 ZonedDateTime，使用系统默认时区
        ZonedDateTime zonedDateTime = tomorrowEightAM.atZone(ZoneId.systemDefault());
        // 将 ZonedDateTime 转换为 Instant 并获取时间戳（毫秒）
        long l = zonedDateTime.toInstant().toEpochMilli();
        Timestamp creatTime = new Timestamp(l);
        // 获取明天的投放计划
        List<ForeshowVo> foreshowVos = deviceCurrentComboStockService.deviceComboForecast(machineId, creatTime);
        if (foreshowVos.isEmpty()) {
            return R.ok();
        }
        Map<String, ForeshowVo> foreshowVoMap = foreshowVos.stream().collect(Collectors.toMap(ForeshowVo::getComboId, Function.identity()));
        Set<String> comboIds = foreshowVoMap.keySet();
        // 标签
        List<ComboLabel> comboLabels = comboMapper.findByComboIdsTag(comboIds);
        // 背景图
        List<Combo> comboUrls = comboMapper.findByComboIdsUrl(comboIds);
        Map<String, String> urlMap = comboUrls.stream().collect(Collectors.toMap(Combo::getComboId, Combo::getThumbUrl));
        List<ForeshowVo> foreshowVoList = new ArrayList<>();

        for (String comboId : comboIds) {
            ForeshowVo foreshowVo = foreshowVoMap.get(comboId);
            List<ComboLabel> Labels = comboLabels.stream().filter(comboLabel -> comboLabel.getComboId().equals(comboId)).collect(Collectors.toList());
            foreshowVo.setComboLabel(Labels);
            String url = urlMap.get(comboId);
            foreshowVo.setThumbUrl(url);
            foreshowVoList.add(foreshowVo);
        }
        return R.ok(foreshowVoList);
    }


    /**
     * 获取投放计划
     *
     * @return
     */
    @Override
    public R<List<ReplenishVo>> devicePlacementPlanSyncPreview() {
        // 获取设备信息
        String machineId = SecurityUtils.getUsername();
        if (StringUtils.isEmpty(machineId)) {
            log.info("设备未登录");
            return R.fail("设备未登录");
        }
//        String machineId = "24051302000038";
        long l = System.currentTimeMillis();
        // 获取当前的时间
        Timestamp currentTime = new Timestamp(l);
        List<DeviceCurrentComboPlanRoad> list = deviceCurrentComboPlanRoadMapper.getByMachineIdAndDate(machineId, currentTime);
        if (list.isEmpty()) {
            log.info("没有投放计划，设备id:{}", machineId);
            return R.fail(machineId + "没有投放计划");
        }
        List<ReplenishVo> replenishVos = noticeMachine(list);
        //
        // // 计算预估到手价格
        // // 列表中的套餐需要分别判断，分别取优惠力度最大优惠券的预估金额
        // List<ReplenishDTO> replenishDTOS = BeanUtil.copyToList(replenishVos, ReplenishDTO.class);
        // // 根据套餐id去重
        // List<ReplenishDTO> values = replenishDTOS.stream().collect(Collectors.toMap(ReplenishDTO::getComboId, Function.identity(), (e1, e2) -> e1)).values().stream().toList();
        // Response<Map<String, ReplenishDTO.Marketing>> mapResponse = remoteClientService.computeEstimatedPrice(machineId, values);
        // if (mapResponse.getCode().equals(ResponseEnum.OPERATOR_SUCCESS.getCode())) {
        //     Map<String, ReplenishDTO.Marketing> data = mapResponse.getData();
        //     replenishVos.stream().peek(item -> {
        //         ReplenishDTO.Marketing marketing = data.get(item.getComboId());
        //         ReplenishDTO.Marketing bean = BeanUtil.toBean(marketing, ReplenishDTO.Marketing.class);
        //
        //         ReplenishVo.Marketing marketing1 = item.getMarketing();
        //         marketing1.setDiscountedAfterPrice(bean.getDiscountedAfterPrice());
        //         marketing1.setClientCouponId(bean.getClientCouponId());
        //     }).collect(Collectors.toList());
        // } else {
        //     replenishVos.stream().peek(item -> {
        //         ReplenishVo.Marketing marketing1 = item.getMarketing();
        //         marketing1.setDiscountedAfterPrice(BigDecimal.valueOf(marketing1.getApplietAmount()));
        //     }).collect(Collectors.toList());
        // }
        return R.ok(replenishVos);
    }


    /**
     * 提交投放计划
     *
     * @return
     */
    @Override
    @Transactional
    public R<List<ReplenishVo>> devicePlacementPlanSync() {
        // 获取设备信息
        String machineId = SecurityUtils.getUsername();
        if (StringUtils.isEmpty(machineId)) {
            log.info("设备未登录");
            return R.fail("设备未登录");
        }
        SysOperationLog sysOperationLog = new SysOperationLog();
        sysOperationLog.setMachineId(machineId);
        sysOperationLog.setType(1);
        asyncLogService.addOperationLog(sysOperationLog);
//        String machineId = "24051302000038";
        long l = System.currentTimeMillis();
        // 获取当前的时间
        Timestamp currentTime = new Timestamp(l);
        List<DeviceCurrentComboPlanRoad> comboList = deviceCurrentComboPlanRoadMapper.getByMachineIdAndDate(machineId, currentTime);
        if (comboList.isEmpty()) {
            log.info("没有投放计划，设备id:{}", machineId);
            return R.fail(machineId + "没有投放计划");
        }

        // 获取套餐计划id
        String cPlanId = CollUtil.getFirst(comboList).getCPlanId();
        // 清空设备的投放计划信息
        LambdaQueryWrapper<DeviceCurrentComboPlan> deviceCurrentComboPlanLambdaQueryWrapper = new LambdaQueryWrapper<DeviceCurrentComboPlan>().eq(DeviceCurrentComboPlan::getMachineId, machineId);
        deviceCurrentComboPlanMapper.delete(deviceCurrentComboPlanLambdaQueryWrapper);
        deviceCurrentComboPlanRoadMapper.deleteByMachineId(machineId);
        // 清空设备的库存信息
        deviceCurrentComboPlanStockMapper.deleteByMachineId(machineId);
//            // 清掉当前设备今天提交的数据
//            deviceComboPlanNumService.deleteByMachineId(machineId);
        // 更新设备计划
        DeviceCurrentComboPlan dcp = new DeviceCurrentComboPlan();
        dcp.setCPlanId(cPlanId);
        dcp.setMachineId(machineId);
        dcp.setCPlanSnyTime(new Timestamp(System.currentTimeMillis()));
        dcp.setCreateTime(new Timestamp(System.currentTimeMillis()));
        dcp.setUpdateTime(new Timestamp(System.currentTimeMillis()));
        deviceCurrentComboPlanMapper.insert(dcp);
        HashMap<String, DeviceComboPlanNum> planNumDOHashMap = new HashMap<>();

        comboList.forEach(dccpr -> {
            dccpr.setMachineId(machineId);
            dccpr.setCreateTime(new Timestamp(System.currentTimeMillis()));
            dccpr.setUpdateTime(new Timestamp(System.currentTimeMillis()));
            String comboId = dccpr.getComboId();
            if (planNumDOHashMap.containsKey(comboId)) {
                DeviceComboPlanNum planNumDO = planNumDOHashMap.get(comboId);
                Integer num = planNumDO.getComboNum();
                planNumDO.setComboNum(num + Integer.parseInt(dccpr.getComboNum()));
                planNumDOHashMap.put(comboId, planNumDO);
            } else {
                DeviceComboPlanNum deviceComboPlanNumDO = new DeviceComboPlanNum();
                deviceComboPlanNumDO.setCPlanId(cPlanId);
                deviceComboPlanNumDO.setMachineId(machineId);
                deviceComboPlanNumDO.setComboId(comboId);
                deviceComboPlanNumDO.setComboNum(Integer.parseInt(dccpr.getComboNum()));
                deviceComboPlanNumDO.setCreateTime(new Timestamp(System.currentTimeMillis()));
                deviceComboPlanNumDO.setUpdateTime(new Timestamp(System.currentTimeMillis()));
                planNumDOHashMap.put(comboId, deviceComboPlanNumDO);
            }
        });


        // 查询该设备 今日 付过钱没退款的，但是没工单的套餐id
        List<String> comboIds = orderListMapper.getByMachineIdAndStatus(machineId);
        Map<String, Long> countMap = null;
        if (!comboIds.isEmpty()) {
            countMap = comboIds.stream()
                    .collect(Collectors.groupingBy(n -> n, Collectors.counting()));
        }


        ArrayList<DeviceComboPlanNum> deviceComboPlanNumDOS = new ArrayList<>();

        for (String comboId : planNumDOHashMap.keySet()) {
            DeviceComboPlanNum deviceComboPlanNumDO = planNumDOHashMap.get(comboId);
            if (null != countMap && countMap.containsKey(comboId)) {
                // 减掉没取走的数量
                Integer comboNum = countMap.get(comboId).intValue();
                Integer comboNum1 = deviceComboPlanNumDO.getComboNum();
                if (comboNum1 >= comboNum) {
                    deviceComboPlanNumDO.setComboNum(comboNum1 - comboNum);
                } else {
                    deviceComboPlanNumDO.setComboNum(0);
                }
            }
            deviceComboPlanNumDOS.add(deviceComboPlanNumDO);
        }

        // 设备投放量表入库
        deviceComboPlanNumMapper.insertAll(deviceComboPlanNumDOS);

        deviceCurrentComboPlanRoadMapper.insertAll(comboList);

        // 更新库存
        Map<String, DeviceCurrentComboStock> devStock = new HashMap<>();
        comboList.forEach(item -> {
            String comboId = item.getComboId();
            String comboNum = item.getComboNum();
            String machineId1 = item.getMachineId();
            Timestamp date = item.getDate();
            String cpId = item.getCPlanId();
            DeviceCurrentComboStock dcStock = devStock.get(comboId);
            if (dcStock == null) {
                DeviceCurrentComboStock stock = new DeviceCurrentComboStock();
                stock.setDate(date);
                stock.setCPlanId(cpId);
                stock.setComboId(comboId);
                stock.setComboNum(Integer.parseInt(comboNum));
                stock.setMachineId(machineId1);
                stock.setStockSnyTime(new Timestamp(System.currentTimeMillis()));
                stock.setUpdateTime(new Timestamp(System.currentTimeMillis()));
                stock.setCreateTime(new Timestamp(System.currentTimeMillis()));
                devStock.put(comboId, stock);
            } else {
                dcStock.setComboNum(dcStock.getComboNum() + Integer.parseInt(comboNum));
            }
        });

        List<DeviceCurrentComboStock> dccsList = new ArrayList<>();

        // 入库
        for (String comboId : devStock.keySet()) {
            DeviceCurrentComboStock deviceCurrentComboStockDO = devStock.get(comboId);
            if (null != countMap && countMap.containsKey(comboId)) {
                // 减掉没取走的数量
                Integer comboNum = countMap.get(comboId).intValue();
                Integer comboNum1 = deviceCurrentComboStockDO.getComboNum();
                if (comboNum1 >= comboNum) {
                    deviceCurrentComboStockDO.setComboNum(comboNum1 - comboNum);
                } else {
                    deviceCurrentComboStockDO.setComboNum(0);
                }
            }
            dccsList.add(deviceCurrentComboStockDO);
        }

        deviceCurrentComboStockService.insertAll(dccsList);

        // 通知设备
        List<ReplenishVo> replenishVos = noticeMachine(comboList);
        log.info("提交设备投放计划成功，设备id信息:{}", machineId);
        //
        // // 计算预估到手价格
        // // 列表中的套餐需要分别判断，分别取优惠力度最大优惠券的预估金额
        // List<ReplenishDTO> replenishDTOS = BeanUtil.copyToList(replenishVos, ReplenishDTO.class);
        // // 根据套餐id去重
        // List<ReplenishDTO> values = replenishDTOS.stream().collect(Collectors.toMap(ReplenishDTO::getComboId, Function.identity(), (e1, e2) -> e1)).values().stream().toList();
        // Response<Map<String, ReplenishDTO.Marketing>> mapResponse = remoteClientService.computeEstimatedPrice(machineId, values);
        // if (mapResponse.getCode().equals(ResponseEnum.OPERATOR_SUCCESS.getCode())) {
        //     Map<String, ReplenishDTO.Marketing> data = mapResponse.getData();
        //     replenishVos.stream().peek(item -> {
        //         ReplenishDTO.Marketing marketing = data.get(item.getComboId());
        //         ReplenishDTO.Marketing bean = BeanUtil.toBean(marketing, ReplenishDTO.Marketing.class);
        //
        //         ReplenishVo.Marketing marketing1 = item.getMarketing();
        //         marketing1.setDiscountedAfterPrice(bean.getDiscountedAfterPrice());
        //         marketing1.setClientCouponId(bean.getClientCouponId());
        //     }).collect(Collectors.toList());
        // } else {
        //     replenishVos.stream().peek(item -> {
        //         ReplenishVo.Marketing marketing1 = item.getMarketing();
        //         marketing1.setDiscountedAfterPrice(BigDecimal.valueOf(marketing1.getApplietAmount()));
        //     }).collect(Collectors.toList());
        // }
        return R.ok(replenishVos);
    }


    /**
     * 修改库存
     *
     * @param dccprs
     * @return
     */
    @Override
    @Transactional
    public R<?> deviceComboStockSync(List<DeviceCurrentComboPlanRoad> dccprs) {
        if (dccprs != null) {
            Timestamp timestamp = new Timestamp(System.currentTimeMillis());
            // 获取设备id
            String machineId = SecurityUtils.getUsername();
            if (StringUtils.isEmpty(machineId)) {
                log.info("设备未登录");
                return R.fail("设备未登录");
            }
            SysOperationLog sysOperationLog = new SysOperationLog();
            sysOperationLog.setMachineId(machineId);
            sysOperationLog.setParameter(dccprs.toString());
            sysOperationLog.setType(3);
            asyncLogService.addOperationLog(sysOperationLog);
//            String machineId = "24051302000038";
//            String machineId = CollUtil.getFirst(dccprs).getMachineId();
            for (DeviceCurrentComboPlanRoad dccpr : dccprs) {
                dccpr.setMachineId(machineId);
            }

            // 当前货道信息
            List<DeviceCurrentComboPlanRoad> roadDOList = deviceCurrentComboPlanRoadMapper.roadInfo(machineId);
            Map<String, DeviceCurrentComboPlanRoad> roadDOMap = roadDOList.stream().collect(Collectors.toMap(DeviceCurrentComboPlanRoad::getRoadNumber, Function.identity()));
            // 存每种套餐的变化数量   是应该加还是减
            HashMap<String, Integer> comboNumMap = new HashMap<>();
            for (DeviceCurrentComboPlanRoad dccpr : dccprs) {
                Integer num = Integer.parseInt(dccpr.getComboNum());
                if (roadDOMap.containsKey(dccpr.getRoadNumber())) {
                    DeviceCurrentComboPlanRoad roadDO = roadDOMap.get(dccpr.getRoadNumber());
                    num -= Integer.parseInt(roadDO.getComboNum());
                }
                if (comboNumMap.containsKey(dccpr.getComboId())) {
                    Integer integer = comboNumMap.get(dccpr.getComboId());
                    comboNumMap.put(dccpr.getComboId(), num + integer);
                } else {
                    comboNumMap.put(dccpr.getComboId(), num);
                }
            }

            ArrayList<DeviceCurrentComboPlanRoad> dccprList = new ArrayList<>();
            ArrayList<DeviceComboPlanNum> dcpnList = new ArrayList<>();
            ArrayList<DeviceCurrentComboStock> dccsList = new ArrayList<>();


            // 获取当前线上库存
            List<DeviceCurrentComboStock> stockDOS = deviceCurrentComboStockService.getByMacineId(machineId);
            Map<String, DeviceCurrentComboStock> stockDOMap = stockDOS.stream().collect(Collectors.toMap(DeviceCurrentComboStock::getComboId, Function.identity()));
            for (String comboId : stockDOMap.keySet()) {
                if (comboNumMap.containsKey(comboId)) {
                    // 套餐变化数量
                    Integer comboNum = comboNumMap.get(comboId);
                    DeviceCurrentComboStock deviceCurrentComboStockDO = stockDOMap.get(comboId);
                    Integer comboNum1 = deviceCurrentComboStockDO.getComboNum();
                    if ((comboNum1 + comboNum) < 0) {
                        throw new ServiceException("修改库存失败，修改后的套餐数量不能小于已售但未取餐的数量");
                    }
                    deviceCurrentComboStockDO.setComboNum(comboNum1 + comboNum);
                    log.info("线上库存:{},套餐变化数量:{}",deviceCurrentComboStockDO.getComboNum(),comboNum);
                    dccsList.add(deviceCurrentComboStockDO);
                }
            }

            // 获取投放记录
//                List<String> comboIds = deviceComboPlanNumMapper.getCPlanComboIds(machineId);
            List<DeviceComboPlanNum> numDOS = deviceComboPlanNumMapper.getByMacineId(machineId);
            Map<String, DeviceComboPlanNum> numDOMap = numDOS.stream().collect(Collectors.toMap(DeviceComboPlanNum::getComboId, Function.identity()));
            for (String comboId : numDOMap.keySet()) {
                if (comboNumMap.containsKey(comboId)) {
                    Integer comboNum = comboNumMap.get(comboId);
                    DeviceComboPlanNum deviceComboPlanNumDO = numDOMap.get(comboId);
                    Integer comboNum1 = deviceComboPlanNumDO.getComboNum();
                    deviceComboPlanNumDO.setComboNum(comboNum1 + comboNum);
                    dcpnList.add(deviceComboPlanNumDO);
                }
            }



            dccprs.forEach(dccpr -> {
                dccpr.setUpdateTime(timestamp);
                dccprList.add(dccpr);
            });
            deviceCurrentComboPlanRoadMapper.batchUpdate(dccprList);


            HashMap<String, DeviceCurrentComboPlanRoad> map = new HashMap<>();
            dccprs.forEach(dccpr -> {
                if (map.containsKey(dccpr.getComboId())) {
                    DeviceCurrentComboPlanRoad aDo = map.get(dccpr.getComboId());
                    Integer num = Integer.parseInt(aDo.getComboNum()) + Integer.parseInt(dccpr.getComboNum());
                    aDo.setComboNum(num.toString());
                    map.put(dccpr.getComboId(), aDo);
                } else {
                    map.put(dccpr.getComboId(), dccpr);
                }
            });

//            for (String key : map.keySet()) {
//                DeviceCurrentComboPlanRoad roadDO = map.get(key);
//                DeviceCurrentComboStock deviceCurrentComboStockDO = new DeviceCurrentComboStock();
//                deviceCurrentComboStockDO.setComboNum(Integer.parseInt(roadDO.getComboNum()));
//                deviceCurrentComboStockDO.setComboId(roadDO.getComboId());
//                deviceCurrentComboStockDO.setMachineId(roadDO.getMachineId());
//                deviceCurrentComboStockDO.setUpdateTime(new Timestamp(System.currentTimeMillis()));
//                deviceCurrentComboStockDO.setStockSnyTime(new Timestamp(System.currentTimeMillis()));
//                dccsList.add(deviceCurrentComboStockDO);
//
//                // 设备投放量记录
//                DeviceComboPlanNum countDO = new DeviceComboPlanNum();
//                countDO.setComboNum(Integer.parseInt(roadDO.getComboNum()));
//                countDO.setMachineId(roadDO.getMachineId());
//                countDO.setComboId(roadDO.getComboId());
//                countDO.setUpdateTime(timestamp);
//                dcpnList.add(countDO);
//            }


            deviceComboPlanNumMapper.batchUpdate(dcpnList);
            deviceCurrentComboStockService.batchUpdate(dccsList);
        }
        return R.ok();
    }


    /**
     * 立即制作套餐
     *
     * @param makePackageDTO
     * @return
     */
//    @Override
//    @Transactional
//    public R<?> makePackage(MakePackageDTO makePackageDTO) {
//
//        String orderId = makePackageDTO.getOrderId();
//        // 查看订单状态
//        List<OrderList> orderList = orderListMapper.getByPayOrderId(orderId);
//        if (orderList.isEmpty()) {
//            log.info("订单未支付");
//            return R.fail("订单未支付");
//        }
//
//        List<OrderDetail> orderDetailList = makePackageDTO.getOrderDetailList();
//        // 查询订单是否有已制作套餐
//        long count = 0;
//        List<String> detailIds = orderDetailList.stream().map(orderDetail -> orderDetail.getOrderDetailId()).collect(Collectors.toList());
//        // 批量查询详情列表
//        List<OrderDetail> detailList = orderDetailService.findByDetailIds(detailIds);
//        // 判断订单状态
//        for (OrderDetail orderDetail : detailList) {
//            count += orderDetail.getCount();
//            if (!orderDetail.getStatus().equals(PackageStatus.WaitingToBeMade.getStatus())) {
//                log.info("已有选中的套餐正在制作");
//                return R.fail("已有选中的套餐正在制作");
//            }
//        }
//
//        OrderCombo orderCombo = orderComboService.getById(orderId);
//        String machineId = orderCombo.getMachineId();
//        RLock lock = redissonClient.getLock("makePackage" + machineId);
//        lock.lock();
//
//        // 获取赞存柜信息
//        String key = "temporaryLockers" + machineId;
//        String lockerCount = redisTemplate.opsForValue().get(key);
//        if (lockerCount == null || StringUtils.isEmpty(lockerCount)) {
//            lock.unlock();
//            log.info("无该设备暂存柜信息");
//            return R.fail("无该设备暂存柜信息");
//        }
//        // 校验赞存柜数量
//        long actualCount = Long.parseLong(lockerCount);
//        if (actualCount < count) {
//            lock.unlock();
//            log.info("暂存柜已满，建议去机器扫码取餐");
//            return R.fail("暂存柜已满，建议去机器扫码取餐");
//        }
//        // 推送剩余赞存柜数量
//        lockerCount = actualCount - count + "";
//        redisTemplate.opsForValue().set(key, lockerCount);
//
//        // 获取订单支付时间
//        Date payTime = orderList.get(0).getPayTime();
//
//        // 支付时间
//        makePackageDTO.setPayTime(payTime.getTime());
//        makePackageDTO.setSendTime(System.currentTimeMillis());
//        makePackageDTO.setPickupGoodsType("2TS");
//
//        String userId = orderCombo.getUserId();
//        Client client = clientMapper.selectById(userId);
//        makePackageDTO.setUserHeadUrl(client.getHeadImg());
//        makePackageDTO.setPickupNum(client.getMobile());
//
//        MqttDTO<MakePackageDTO> orderMakeDTOMqttDTO = new MqttDTO<>();
//        orderMakeDTOMqttDTO.setCmd(MqttConstants.MAKE_COMBO);
//        orderMakeDTOMqttDTO.setPayload(makePackageDTO);
//
//        /**
//         * 主题是设备id
//         */
//        mqttGateway.sendToMqtt(machineId, JSONUtil.toJsonStr(orderMakeDTOMqttDTO));
//
//
//        orderComboService.updateCupboardState(orderId);
//
//        redisTemplate.opsForValue().set("makePackage" + orderId, "true", 1, TimeUnit.DAYS);
//        lock.unlock();
//        return R.ok();
//    }

    /**
     * 根据machineId查询设备信息
     *
     * @param machineId
     * @return
     */
    @Override
    public Machine findByMachineId(String machineId) {
        return machineMapper.findByMachineId(machineId);
    }

    /**
     * 定时任务企业发送报警信息
     */
    @Override
    public void sendWeiXin() {
        try {
            List<MachineTempWarn> machineTempWarns = machineTempWarnMapper.findByCreatTime();
            Map<String, List<MachineTempWarn>> machineTempWarnMap = machineTempWarns.stream().collect(Collectors.groupingBy(MachineTempWarn::getMachineId));
            for (String machineId : machineTempWarnMap.keySet()) {
                List<MachineTempWarn> machineTempWarns1 = machineTempWarnMap.get(machineId);
                Machine machine = machineMapper.findByMachineId(machineId);
                String text = "### 异常温度报警" +
                        "\n - 设备编号： " + machine.getMachineSn() +
                        "\n - 设备名称： " + machine.getMachineName();
                String tempTest="";
                for (MachineTempWarn machineTempWarn : machineTempWarns1) {
                    String tempWaren = machineTempWarn.getExceptionTemp().substring(0, machineTempWarn.getExceptionTemp().length()-2);
                    Integer temp = Integer.parseInt(tempWaren);
                    if (temp < 0 || temp > 10){
                        tempTest = tempTest +
                                "\n - 报警时间： " + DateUtils.parseLongToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, Long.parseLong(machineTempWarn.getWarnTime())) +
                                "\n - 当前温度： " + machineTempWarn.getExceptionTemp();
                    }
                }
                if (StringUtils.isNotEmpty(tempTest)){
                    WeixinRobotSender.sendTextMessage(text+tempTest, applicationContext);
                }
                Thread.sleep(1000);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 根据货道号列表添加库存
     * @param updateByMachineIdAndRoadNumDTO
     */
    @Override
    public void updateByMachineIdAndRoadNum(UpdateByMachineIdAndRoadNumDTO updateByMachineIdAndRoadNumDTO) {

        log.info("一键恢复添加库存，参数:{}",updateByMachineIdAndRoadNumDTO);
        if (BeanUtil.isEmpty(updateByMachineIdAndRoadNumDTO)) {
            return;
        }

        String machineId = updateByMachineIdAndRoadNumDTO.getMachineId();
        List<Integer> roadNumbers = updateByMachineIdAndRoadNumDTO.getRoadNumbers();

        // 根据设备id获取货道信息
        List<DeviceCurrentComboPlanRoad> list = deviceCurrentComboPlanRoadMapper.getByMachineId(machineId);
        Map<String, String> roadComboMap = list.stream().collect(Collectors.toMap(DeviceCurrentComboPlanRoad::getRoadNumber, DeviceCurrentComboPlanRoad::getComboNum));

        // key为货道号，value为该货道号出现的次数
        Map<Integer, Long> roadMap = roadNumbers.stream()
                .collect(Collectors.groupingBy(n -> n, Collectors.counting()));

        for (Integer roadNumber : roadMap.keySet()) {

            // 套餐数量
            Long aLong = roadMap.get(roadNumber);
            if (roadComboMap.containsKey(roadNumber.toString())) {
                String num = roadComboMap.get(roadNumber.toString());
                aLong += Long.valueOf(num);
            }
            String comboNum = aLong.toString();
            deviceCurrentComboPlanRoadMapper.addRoadComboNum(machineId,roadNumber.toString(),comboNum);
        }
    }


    /**
     * 获取套餐信息
     *
     * @param comboList
     * @return
     */
    public List<ReplenishVo> noticeMachine(List<DeviceCurrentComboPlanRoad> comboList) {
        // 获取设备优惠金额
        // SysDictData deviceDiscountAmount = sysDictDataService.getByType("device_discount_amount");
        // 获取套餐计划id
        String cPlanId = CollUtil.getFirst(comboList).getCPlanId();
        String machineId = CollUtil.getFirst(comboList).getMachineId();
        List<String> comboIds = comboList.stream().map(s -> s.getComboId()).collect(Collectors.toList());
        LambdaQueryWrapper<Combo> wrapper = new LambdaQueryWrapper<Combo>().in(Combo::getComboId, comboIds);
        List<Combo> combos = comboMapper.selectList(wrapper);
//        List<Combo> comboDOS = comboMapper.findByComboIds(comboIds);
        Map<String, Combo> comboDOMap = combos.stream().collect(Collectors.toMap(Combo::getComboId, Function.identity()));

        List<TagCombo> tagCombos = new ArrayList<>();
        List<String> tagIds = combos.stream().map(comboDO -> comboDO.getTagId()).filter(tagId -> StrUtil.isNotBlank(tagId)).distinct().collect(Collectors.toList());
        if (CollUtil.isNotEmpty(tagIds)) {
            for (String tagId : tagIds) {
                if (StringUtils.isNotEmpty(tagId)) {
                    List<String> strings = Arrays.asList(tagId.split(","));
                    List<TagCombo> list = tagComboMapper.findByTagIds(strings);
                    tagCombos.addAll(list);
                }
            }
        }

        List<Goods> goodsDOList = goodsMapper.getAll();
        Map<String, Goods> goodsDOMap = goodsDOList.stream().collect(Collectors.toMap(Goods::getGoodsId, Function.identity()));

        List<ImgResource> imgResourceDOList = imgResourceMapper.getAll();
        Map<String, ImgResource> imgMap = imgResourceDOList.stream().collect(Collectors.toMap(ImgResource::getImgId, Function.identity()));
        List<ComboGoods> comboGoodsDOs = comboGoodsMapper.getAll();
        // 封装数据返回设备
        List<ReplenishVo> replenishVos = new ArrayList<>();

        ReplenishVo replenishVo = null;
        for (DeviceCurrentComboPlanRoad dccpr : comboList) {
            replenishVo = new ReplenishVo();
            // 套餐id
            replenishVo.setComboId(dccpr.getComboId());
            // 套餐名称
            replenishVo.setComboName(dccpr.getComboName());
            // 套餐数量
            replenishVo.setComboNum(Integer.parseInt(dccpr.getComboNum()));
            // 货道号
            replenishVo.setRoadNumber(Integer.parseInt(dccpr.getRoadNumber()));

            // 创建营销对象
            ReplenishVo.Marketing marketing = replenishVo.new Marketing();

            List<ReplenishVo.ComboLabel> list = new ArrayList<>();
            // 如果套餐map包含该套餐id
            if (comboDOMap.containsKey(dccpr.getComboId())) {
                // 套餐信息
                Combo comboDO = comboDOMap.get(dccpr.getComboId());
                // 保质期
                replenishVo.setExpireDay(comboDO.getExpireDay());
                replenishVo.setHeatTime(comboDO.getHeatTime());
                // 小程序价格
                // String dictValue = deviceDiscountAmount.getDictValue();
                // BigDecimal miniPrice = NumberUtil.sub(comboDO.getSalePrice(), dictValue);
                // if (NumberUtil.isLess(miniPrice, BigDecimal.ZERO)) {
                //     miniPrice = BigDecimal.ZERO;
                // }
                marketing.setApplietAmount(Double.valueOf(comboDO.getMiniPrice()));
                // 设备价格
                marketing.setDeviceAmount(Double.valueOf(comboDO.getSalePrice()));
                // 会员价格
                marketing.setVipAmount(Double.valueOf(comboDO.getVipPrice()));
//                marketingTab.setMarketingId("");
//                marketingTab.setComboId(dccpr.getComboId());
                if (!tagCombos.isEmpty() && comboDO.getTagId() != null) {
                    List<String> tagIdList = Arrays.asList(comboDO.getTagId().split(","));
                    for (String tagId : tagIdList) {
                        if (StringUtils.isEmpty(tagId)){
                            continue;
                        }
                        // 取总标签中的套餐标签信息
                        List<TagCombo> tagComboList = tagCombos.stream().filter(tagCombo -> tagCombo.getTagId().equals(tagId)).collect(Collectors.toList());
                        // 取套餐标记集合第一个
                        TagCombo tagCombo = tagComboList.get(0);
                        ReplenishVo.ComboLabel comboLabel = replenishVo.new ComboLabel();
                        // 套餐标签id 列表 字符窜
                        comboLabel.setLabelName(tagCombo.getTagName());
                        comboLabel.setLevel(0);
                        comboLabel.setColor(tagCombo.getColor());
                        list.add(comboLabel);
                    }
                }
                ImgResource imgResourceDO = imgMap.get(comboDO.getThumb());
                // 套餐图片路径
                replenishVo.setThumbUrl(imgResourceDO.getUrl());
                // 味道
                ReplenishVo.Tastes tastes = replenishVo.new Tastes();
                tastes.setSpicy(Convert.toInt(comboDO.getTaste()));
                replenishVo.setTastes(tastes);
            }
            replenishVo.setMarketing(marketing);
            replenishVo.setComboLabel(list);
            //  套餐配菜
            com.yfp.common.core.domain.R<List<com.yfp.goods.domain.Goods>> goods = remoteGoodsService.queryByComboId(dccpr.getComboId());

            // 套餐组成
            ArrayList<GoodsData> dataArrayList = new ArrayList<>();
            List<ReplenishVo.GoodsData> goodsDataList = new ArrayList<>();
            List<ComboGoods> comboGoodsList = comboGoodsDOs.stream().filter(combogoodsDO -> combogoodsDO.getComboId().equals(dccpr.getComboId())).collect(Collectors.toList());
            ReplenishVo.GoodsData goodsData = null;
            for (ComboGoods comboGoods : comboGoodsList) {
                Goods goodsDO = goodsDOMap.get(comboGoods.getGoodsId());
                // 商品营养表
                com.yfp.common.core.domain.R<List<GoodsNutritive>> rGoodsNutritive = remoteGoodsService.queryGoodsNutritiveByGoodsId(goodsDO.getGoodsId());
                List<GoodsNutritive> goodsNutritives = rGoodsNutritive.getData();
                if (!goodsNutritives.isEmpty()) {
                    for (GoodsNutritive goodsNutritive : goodsNutritives) {
                        goodsData = replenishVo.new GoodsData();
                        goodsData.setGoodsNutritive(goodsNutritive.getNutritive());
                        if (!StrUtil.isEmpty(goodsNutritive.getValue())) {
                            goodsData.setValue(Double.valueOf(goodsNutritive.getValue()));
                        }
                        goodsDataList.add(goodsData);
                    }
                }
            }

            // 查询套餐资源
            com.yfp.common.core.domain.R<List<ComboDetailImg>> comboDetailImg = remoteGoodsService.queryComboDetailImg(dccpr.getComboId());
            List<ComboDetailImg> comboDetailImgs = comboDetailImg.getData();
            List<ReplenishVo.Resource> resourceList = new ArrayList<>();
            ReplenishVo.Resource resource = null;
            for (ComboDetailImg detailImg : comboDetailImgs) {
                resource = replenishVo.new Resource();
                com.yfp.common.core.domain.R<String> rResourceUrl = remoteGoodsService.getResourceUrl(detailImg.getResourceType(), detailImg.getResourceId());
                String resourceUrl = rResourceUrl.getData();
                resource.setResourceType(detailImg.getResourceType() + "");
                resource.setResourceUrl(resourceUrl);
                resourceList.add(resource);
            }
            ReplenishVo.ComboDetailData comboDetailData = replenishVo.new ComboDetailData();
            comboDetailData.setResourceList(resourceList);


            // 套餐组成
            replenishVo.setGoods(goods.getData());
            replenishVo.setGoodsData(goodsDataList);
            replenishVo.setComboDetailData(comboDetailData);
            // 添加集合
            replenishVos.add(replenishVo);
        }
        log.info("noticeMachine消息:{}", JSONUtil.toJsonStr(replenishVos));
        return replenishVos;
    }
}
